/*
 * @Author: ColdV
 * @Date: 2021-08-04 23:02:30
 * @LastEditTime: 2021-08-06 15:39:40
 * @LastEditors: ColdV
 * @Description: 
 * @FilePath: /chaos_alpha/src/common/thread/Thread.cpp
 * 
 */
#include "Thread.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/prctl.h>
#endif // _WIN32

namespace chaos
{
	THREAD_LOCAL thread_t t_curThreadId = 0;

	Thread::Thread(const ThreadFunc& func, const std::string& name/* = ""*/) :
		m_tid(0),
		m_name(name),
		m_func(func),
		m_started(false),
		m_joined(false)
	{
	#ifdef _WIN32
		m_hThread = NULL;
	#endif
	}


	Thread::~Thread()
	{	
		if (m_started && !m_joined)
		{
			if (0 != Join())
			{
	#ifdef _WIN32
				printf("wait thread end failed! force thread.%d\n", GetLastError());
				TerminateThread(m_hThread, -1);
				CloseHandle(m_hThread);
	#else
				pthread_detach(m_tid);
	#endif // _WIN32
			}
		}
	}


	int Thread::Start()
	{
		if (m_started)
			return -1;

#ifdef _WIN32
		m_hThread = (HANDLE)_beginthreadex(NULL, 0, Work, (void*)this, 0, &m_tid);
		if (!m_hThread)
			return -1;
#else
		
		if (0 != pthread_create(&m_tid, NULL, Work, (void*)this))
			return -1;
#endif // _WIN32
		m_started = true;

		return 0;
	}


	int Thread::Join()
	{
		if (m_joined || !m_started)
			return 0;

		m_joined = true;
		int ret = 0;
	#ifdef _WIN32
		if (!m_hThread)
			return 0;

		ret = WaitForSingleObject(m_hThread, INFINITE);

		if (0 == ret)
			CloseHandle(m_hThread);
		else
			m_joined = false;
	#else
		ret = pthread_join(m_tid, NULL);
		if (0 != ret)
			m_joined = false;
	#endif // _WIN32

		return ret;
	}


	THREAD_FUNCTION_PRE Thread::Work(void* args)
	{
		assert(args);
		Thread* self = static_cast<Thread*>(args);

		if (!self->m_name.empty())
		{
#ifdef _WIN32
			SetThreadDescription(GetCurrentThread(), self->m_name);
#else
			prctl(PR_SET_NAME, self->m_name.c_str());
#endif //_WIN32
		}
		if (self->m_func)
			self->m_func();
	}
}	// namespace chaos
